/*
 * Ken Anderson, 2009
 */

#include "EventHandler.h"
#include "util.h"

#define WINDOW_WIDTH 500
#define WINDOW_HEIGHT 500

WorldState::WorldState()
{
	mDone = false;
	mNewStart = false;
	mNewGoal = false;
	mResetWindow = false;
	mCycleSearch = false;
	mShowLevel0 = true;
	mShowLevel1 = false;
	mShowLevel2 = false;
	mWindowWidth = WINDOW_WIDTH;
	mWindowHeight = WINDOW_HEIGHT;
	mFrameRate = 0.0;
	mXRotationAngle = 0.0;
	mYRotationAngle = 0.0;
	xOffset = 0.0;
	yOffset = 0.0;
	mKeyScrollLeft = 0;
	mKeyScrollRight = 0;
	mKeyScrollUp = 0;
	mKeyScrollDown = 0;
	mKeyRotateLeft = 0;
	mKeyRotateRight = 0;
	mKeyRotateUp = 0;
	mKeyRotateDown = 0;
	mKeyZoomIn = 0;
	mKeyZoomOut = 0;
	zDistance = -15;		// Default value.
}

WorldState::~WorldState()
{
}

EventHandler::EventHandler(WorldState* worldState)
{
	mWorldState = worldState;
	mMouseLeft = false;
	mMouseMiddle = false;
	mMouseRight = false;
}

// Waits for events to happen
void EventHandler::HandleEvent(SDL_Event* event)
{
	switch(event->type) {
		case SDL_KEYDOWN:
			HandleKeyDownEvent(&(event->key.keysym));
			break;

		case SDL_KEYUP:
			HandleKeyUpEvent(&(event->key.keysym));
			break;

		case SDL_MOUSEBUTTONDOWN:
			HandleMouseButtonEvent(&(event)->button);
			break;

		case SDL_MOUSEBUTTONUP:
			HandleMouseButtonEvent(&(event)->button);
			break;

		case SDL_MOUSEMOTION:
			HandleMouseMotionEvent(&(event->motion));
			break;

		case SDL_VIDEORESIZE:
			HandleWindowResize(&(event->resize));
			break;

		case SDL_QUIT:
			mWorldState->mDone = true;
			break;

		default:
			break;
	}       
}

void EventHandler::HandleMouseButtonEvent( SDL_MouseButtonEvent* button )
{
	switch(button->button)
	{
		case SDL_BUTTON_LEFT:
			switch( button->state )
			{
				case SDL_PRESSED :
					mMouseLeft = true;
					SDL_ShowCursor( SDL_DISABLE );		// Hide cursor
					SDL_WM_GrabInput( SDL_GRAB_ON );	// Grab hold of the mouse.  Relative movements work at edge of window!
					break;
				case SDL_RELEASED:
					mMouseLeft = false;
					SDL_ShowCursor( SDL_ENABLE );		// Show cursor
					SDL_WM_GrabInput( SDL_GRAB_OFF );	// Release the mouse.
					break;
				default:
					break;
			}
			break;
		case SDL_BUTTON_RIGHT:
			switch( button->state )
			{
				case SDL_PRESSED:
					mMouseRight = true;
					SDL_ShowCursor( SDL_DISABLE );		// Hide cursor
					SDL_WM_GrabInput( SDL_GRAB_ON );	// Grab hold of the mouse. 
					break;
				case SDL_RELEASED:
					mMouseRight = false;
					SDL_ShowCursor( SDL_ENABLE );		// Show cursor
					SDL_WM_GrabInput( SDL_GRAB_OFF );	// Release the mouse.
					break;
			}
			break;
		case SDL_BUTTON_MIDDLE:
			switch( button->state )
			{
				case SDL_PRESSED:
					mMouseMiddle = true;
					SDL_ShowCursor( SDL_DISABLE );		// Hide cursor
					SDL_WM_GrabInput( SDL_GRAB_ON );	// Grab hold of the mouse. 
					break;
				case SDL_RELEASED:
					mMouseMiddle = false;
					SDL_ShowCursor( SDL_ENABLE );		// Show cursor
					SDL_WM_GrabInput( SDL_GRAB_OFF );	// Release the mouse.
					break;
			}
			break;
		case SDL_BUTTON_WHEELUP:
			if( button->state == SDL_RELEASED )			// Only handle one of the two events
				mWorldState->zDistance += 0.5;
			break;
		case SDL_BUTTON_WHEELDOWN:
			if( button->state == SDL_RELEASED )
				mWorldState->zDistance -= 0.5;
			break;
		default:
			break;
	}
}

void EventHandler::HandleMouseMotionEvent( SDL_MouseMotionEvent* motion )
{
	if( mMouseLeft )
	{
		mWorldState->mXRotationAngle += motion->yrel;
		mWorldState->mXRotationAngle = Mod(mWorldState->mXRotationAngle, 360.0);
		mWorldState->mYRotationAngle += motion->xrel;
		mWorldState->mYRotationAngle = Mod(mWorldState->mYRotationAngle, 360.0);
	}
	else if( mMouseMiddle )
	{
		mWorldState->zDistance += motion->yrel;
	}
	else if( mMouseRight )
	{
		mWorldState->xOffset += motion->xrel / 10.0f;
		mWorldState->yOffset -= motion->yrel / 10.0f;
	}

}

void EventHandler::HandleWindowResize( SDL_ResizeEvent* resize )
{
	mWorldState->mWindowWidth = resize->w;
	mWorldState->mWindowHeight = resize->h;
	mWorldState->mResetWindow = true;
}

void EventHandler::HandleKeyDownEvent(SDL_keysym* keysym)
{
	switch (keysym->sym)
	{
		case SDLK_LEFT:
			mWorldState->mKeyScrollLeft = 1;
			break;
		case SDLK_RIGHT:
			mWorldState->mKeyScrollRight = 1;
			break;
		case SDLK_UP:
			mWorldState->mKeyScrollUp = 1;
			break;
		case SDLK_DOWN:
			mWorldState->mKeyScrollDown = 1;
			break;
		case SDLK_EQUALS:	// Cannot use '+', requires shift button
			mWorldState->mKeyZoomIn = 1;
			break;
		case SDLK_MINUS:
			mWorldState->mKeyZoomOut = 1;
			break;
		case SDLK_0:
			mWorldState->mShowLevel0 = !mWorldState->mShowLevel0;
			break;
		case SDLK_1:
			mWorldState->mShowLevel1 = !mWorldState->mShowLevel1;
			break;
		case SDLK_2:
			mWorldState->mShowLevel2 = !mWorldState->mShowLevel2;
			break;
		default:
			break;
	}
}

void EventHandler::HandleKeyUpEvent(SDL_keysym* keysym)
{
	switch (keysym->sym)
	{
		case SDLK_ESCAPE:
			mWorldState->mDone = true;
			break;
		case SDLK_LEFT:
			mWorldState->mKeyScrollLeft = 0;
			break;
		case SDLK_RIGHT:
			mWorldState->mKeyScrollRight = 0;
			break;
		case SDLK_UP:
			mWorldState->mKeyScrollUp = 0;
			break;
		case SDLK_DOWN:
			mWorldState->mKeyScrollDown = 0;
			break;
		case SDLK_EQUALS:
			mWorldState->mKeyZoomIn = 0;
			break;
		case SDLK_MINUS:
			mWorldState->mKeyZoomOut = 0;
			break;
		case SDLK_t:
			mWorldState->mNewStart = 1;
			break;
		case SDLK_g:
			mWorldState->mNewGoal = 1;
			break;
		case SDLK_s:
			mWorldState->mCycleSearch = 1;
		default:
			break;
	}
}

void EventHandler::HandleUserEvent(SDL_Event* event)
{

}
